/*
编写一个 HTTP 服务器，大家视个人不同情况决定完成到哪个环节，但尽量把 1 都做完：

1接收客户端 request，并将 request 中带的 header 写入 response header
2读取当前系统的环境变量中的 VERSION 配置，并写入 response header
3Server 端记录访问日志包括客户端 IP，HTTP 返回码，输出到 server 端的标准输出
4当访问 localhost/healthz 时，应返回 200
*/

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/pprof"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

/*
1.接收客户端 request，并将 request 中带的 header 写入 response header
2.读取当前系统的环境变量中的 VERSION 配置，并写入 response header
4.当访问 localhost/healthz 时，应返回 200
*/

func rootHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("entering root handler")
	//w只响应一次
	if os.Getenv("VERSION") == "" {
		os.Setenv("VERSION", "v1.0")
	}
	var version = os.Getenv("VERSION")
	w.Header().Set("VERSION", version)
	io.WriteString(os.Stdout, fmt.Sprintf("env VERSION = %s\n", version))
	for k, v := range r.Header {
		for _, vv := range v {
			w.Header().Set(k, vv)
			//	io.WriteString(os.Stdout, fmt.Sprintf("%s=%s\n", k, vv))
		}
	}
	log.Printf("http response header list:\n")
	for k, v := range w.Header() {
		for _, vv := range v {
			log.Printf("%s=%s\n", k, vv)
		}
	}

	clientip := getIPImproved(w, r)
	log.Printf("Success! Response code: %d", 200)
	log.Printf("Success! clientip: %s", clientip)
	w.Write([]byte("<!DOCTYPE html><h1>Welcome</h1></html>"))

}

/*
func getCurrentIP(r *http.Request) string {
	ip := r.Header.Get("X-Real-IP")
	if ip == "" {
		ip = strings.Split(r.RemoteAddr, ":")[0]
	}
	return ip
}
*/

//增强的获取IP方法
func getIPImproved(httpWriter http.ResponseWriter, httpServer *http.Request) string {
	var userIP string
	if len(httpServer.Header.Get("CF-Connecting-IP")) > 1 {
		userIP = httpServer.Header.Get("CF-Connecting-IP")
	} else if len(httpServer.Header.Get("X-Forwarded-For")) > 1 {
		xForwardedFor := httpServer.Header.Get("X-Forwarded-For")
		userIP = strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
	} else if len(httpServer.Header.Get("X-Real-IP")) > 1 {
		userIP = strings.TrimSpace(httpServer.Header.Get("X-Real-Ip"))
	} else {
		userIP = httpServer.RemoteAddr
		if strings.Contains(userIP, ":") {
			userIP = strings.Split(userIP, ":")[0]
		}
	}
	io.WriteString(os.Stdout, fmt.Sprintf("client ip is %s\n", userIP))
	return userIP
}

//4当访问 localhost/healthz 时，应返回 200
func healthz(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "working")
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", rootHandler)
	mux.HandleFunc("/healthz", healthz)
	// debug
	mux.HandleFunc("/debug/pprof/", pprof.Index)
	mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
	mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	mux.HandleFunc("/debug/pprof/trace", pprof.Trace)

	srv := &http.Server{
		Addr:    ":8080",
		Handler: mux,
	}
	// Start HTTP server.
	go func() {
		if err := srv.ListenAndServe(); err != nil {
			log.Println("http server: listen and serve:", err)
		}
	}()
	log.Println("app: started")

	// graceful stop
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGTERM)
	log.Println("app: received a shutdown signal:", <-sigs)

	// Allow live connections a set period of time to complete.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
	defer cancel()

	// Shutdown HTTP server.
	if err := srv.Shutdown(ctx); err != nil && err != http.ErrServerClosed {
		log.Println("app: dirty shutdown:", err)
		return
	}

	log.Println("app: clean shutdown")

}
